Now Loading ...
-
Android Static Analysis
Static Analysis
It’s about examining the code without executing the program
We are going to see the important files within the android application and how can we benefit from them
Android Manifest.xml
It contains the basic info about the application
minSDKVersion : which will give us info about the version and then we can detect vulnerability depending on just the version
package name : It’s a unique identifier for the application on the device
As an attacker we address the application through this identifier in our tools and scripts, so it’s important information for us
Permissions
What data & HW components the app needs access to: (camera, BT, internet, etc..)
You can see list of permissions here
Permissions other than uses-permission are more interesting for us. These permissions are defined by the application and if you perform specific task and want to share it with other application then they can request this permission to exchange the data between each other.
Queries
It may contain application we want to exchange data with and to do that we need to be visible to it
<queries>
<package android:name="com.mwr.example.sieve"/>
</queries>
In this example we became visible to sieve application so we can exchange data with it.
We can use that when we write our attacking app to bypass login screen as example.
application
We can see many entries like:
allow backup="true" : This means that the data can be backed up (may be senstive or not)
debuggable="true" : we are allowed to debug this process of the application
extractNativeLibs="false" : If we have native libs included they can’t be compressed (not important for us), we will need it to be false when we inject frida
neworkSecurityConfig=".." : Important in dealing with ssl pinning and if it’s not included we can define it (we will talk more about it later)
In the appliction we have many components (what the app has in the background)
Activities
UI element that represents screens in the application (some of them need to be protected)
protection is done using intent-filters which says (before you go to this screen you need to go to through this screen based on factors like cookies)
exported="True" means that this activity is exposed and can be accessed from outside the app
Intent-Filter
They are filters listening to specific intents and we will discuss them later
service
It gots executed in the background as it may be resource intensive and not allowed to be done on UI
broadcast receiver
It receive info to the application like receiving sms or any data from other application
It’s an important attack surface
Content Providers
serve data from ur app to other apps
most of the time it’s related to database
exported content provider can be very dangerous and expose data to any user or app
the xml tag is provider
You may find API keys defined
At the top of the manifest you can see backup option
We will discuss these parts in more details
permissions
Each app in android system is sandboxed which means that app1 can’t access the data of app2
This is implemented by making use of the linux core of android by creating user for each application, so each app can’t access the others because it willnot have the privileges by default.
/etc/permission/platform.xml : this file defines the users’ IDs which are individual for each app
But what if app wants to access another app or utility like photos, etc….
this is defined in /etc/system/packages.xml
There are users who should be active before the system starts (hardcoded in kernel) like adb shell.
this is defined in android_filesystem_config.h
Now we need to know how can we ask for permission ???
we knew that we can see that defined permissions in AndroidManifest.xml file
and these permission will be added to /etc/system/packages.xml
What about custom permissions ??
It makes the apps exchange data between each others
This permission is defined not used directly
as example
```xml
This permission allows reading keys table in sieve application
When we go to content provider we will understand this more
and this defined permission can be used in another app like this
```xml
<uses-permission ns0:name="com.mwr.example.sieve.READ_KEYS"/>
protection of data is depending on choosing the suitable protection level
We have levels:
dangerous : The user is informed about this and the user decides to allow or deny (depending on user decision isn’t the best case)
normal : You won’t be informed and this isn’t considered a protection for senstive data, but it’s important for things like internet which doesn’t need to be decision before being used
signature : Each apps signed with the same key can access the data (to access database as example which is protected by signtature level then we need the private key of the sieve to access it) This isn’t practicle approach as private key can’t be shared.
activity
basically they are the screens of the application.
as example we may have login activity, profile activity, settings activity, code activity
There are activities like profile as example who need us to login first before accessing it
We see that the only visible activity or the frontline of our app is login page as example, so what if we want to reach the code activity directly by scanning QR code from QR scanner app directly?
The QR scanner must be able to see the code activity and this moves us to exported: which means that the activity is reachable by outside world (dangerous and handled by intents which will be discussed later)
We can know if the activity is exported or not from AndroidManifest.xml file and exported can be implicit and explicit:
explicit : occures when the activity has the attribute exported="true"
implicit : occurs if the activity has intent-filter so it’s also reachable from outside world
Exported scheme doesn’t only affect activities
we can make access exported activity using malicious app or adb shell
after getting adb shell we use the command am which is activity manager but we need to identify the activity to be opened
the activity is identified to be <package name>/<activity name(keep the dot)> so the command becomes am start-activity -n <package name>/<activity name(keep the dot)>
intents
It’s a messaging object and it can be implict and explicit
implicit : We don’t know the exact destination application like we know it’s email app but we don’t know which app exactly
explicit : We know the destination we want to call and the destination can be in the same app or in a different app
It doesn’t work with activities only but also services and BroadcastReceivers
Explicit Intents
Consider you have login activity and you want to login to reach profile activity, this can be implemented like this in login activity source code
Intent myIntent = new Intent(this,ProfileActivity.class); // defining the intent by passing the source and the target
this.startActivity(myIntent);
If we want to start the new activity with parameters
Intent myIntent = new Intent(this,ProfileActivity.class); // defining the intent by passing the source and the target
myIntent.putExtra("username","admin"); // passing username parameter with value = "admin"
this.startActivity(myIntent);
and the parameter is used in the profile activity like this
@Override
Protected void onCreate(Bundle savedInstanceState){
Intent intent = getIntent();
String user = intent.getStringExtra("username"); // get the passed parameter username
}
Implicit Intents
Here we said that we don’t know the destination exactly as example we did an action that send mail and the exact mail app isn’t choosed.
The system sends out this intent and we want to open mail app to do this action (gmail app may be opened as example) but we will know more details in BroadcastReceiver.
If parameters are passed with the intent then there’s an attack vectorif the passed data are sensitive as we can create malicious app that listens to this type of intents (mail as example) and it will sniff the system for this information and this is called Intent - Sniffing
Intent-Filter
As example the main activity will have an intent-filter with action:MAIN and category:LAUNCHER.
It’s just listening to bus system and filtering out the info related to the app we need to react with and ignore the others
It has certain tags : action, category and data
we can know more about them and the possible values here
Note: if you want to interact with intent-filter which is considered implicit use this command am start-activity -a <action> -c <category> --es <key> <value>
–es is to pass key value pair data as string
If there’s many apps with the same action, category the user will choose which app to use
BroadcastReceiver
They are a kind of notification system for ur applications.
There’s a specific events like connecting the headphone, connecting to wifi, etc…. these events are sent as broadcast to all apps
Not all apps react to this, some of them ignore it and the other can react to it through onReceive method.
ordered priority
It was an issue at android 4.3
each app is assigned a specific priority (as example sms has the highest priority = 200)
So it will be the first app to receive the msg and can decide to leave it to the next app with lower priority or not
The problem that in android <= 4.3 The attacker was able to assign it’s app a priority up to 999.
This is fixed in android 4.4 and the priority assignment is limited now.
To find which event each app is listening to, There are 2 approaches:
old approach (until Android version 8): in AndroidManifest.xml
new approach: Finding onReceive function within the Java code
In some broadcast events important data are passed so if we could receive them we may be able to move forward in the target.
Local broadcast manager can’t be exploited because we can’t interact with it, It’s just a messages bewtween classes as example.
adb.exe logcat: to show logging of the app
to open local console we use adb.exe local => this is console at which we can get the output of print function
Sending broadcast through adb: am broadcast -a <action in the intent filter or from the source code depending on android version>
we may not have the permission, so make sure u r root
pm -U: List packages with uid so we can broadcast to specific uid and replcace a with 10, so the broadcast command can be am broadcast --user <uid> -a <action>
If there’s string info to be sent with the Intent filter we can use --es option as we know.
Services
Consider you have a game and it needs some processes like rendering the game and organization of objects (in UI) and we also need network requesting as example.
If all these components are in the main activity we will have a problem: The network request may stop the UI thread until the request is done which may result in closing the app (the app in android is closed if the UI thread isn’t working for some seconds).
The solution is to make the components which isn’t in the UI to be services in background
We have 2 types of services: start service & bound service
start : very simple just the service started when we need it to do some task then close it.
bound : binding client to service (we may have client interacting with the app) then we need to wait for the clients to disconnect to shutdown this service
The services can’t make UI updates as they work in the background
If we want to do so we may make use of BroadcastReceiver and make them trigger the service via onReceive()
This was the common behvior till android 8 cause this background execution isn’t allowed any more.
What to look for ?
start : here you will look into intent
bound : look into the message object
to attack the service it needs to be Exported and Permissions to interact with this one.
ContentProvider
It’s simply provide a content and usually it’s used with databases, we can interact with them via content URI.
as example The Contacts they are stored in db and there’s content provider for this data base.
content URI is used to interact with them and in consists of:
prefix : which is content:// and it’s a good keyword to search for when reversing the app
authorty : It’s a unique identifier for the content provider
table entry
row in table
Content provider are excluded from intents so interaction with them is done in different way like using adb shell and then the command will be $ content query --uri content://com.android.contacts/contacts/1
What if we don’t have adb shell access, so we will write our malicious app.
in our app we want to define ContentResolver that asks the content provider to provide the content to us
we need 2 use cases:
Having permissions
Exported: True
Then after asking, thew content provider returns a Cursor(pointer to data in db) to our app
The content provider must include query, update, insert and delete methods and we will use them in the resolver for interaction with the provider
The data base of custom content provider are stored in data/data/<package>/db
Here we see the structure of query function and how it’s mapped to sql query.
and here we see a basic application of sqli.
content providers aren’t invoked by intents so to interact with it, it must be exported.
ContentProvider can also read and write files this moves us to path traversal vulenerability.
Let’s look in accessing file using content provider
we see that the file is vulenrable to path traversal so the app can get pin.xml file in this example
The content provider is exported if we have read or write permissions, but the protection level may prevent us from exploitation if it’s signature.
protection level dangerous can be ok if the data is encrypted.
from the source code we can reach the implementation information of db like the database.db file and the tables’ names.
note: if table name is db structure source code = key and it’s refrenced in the manifest as keys we will use key in sqli.
interaction with content provider using adb shell is done using content query|insert|... --uri <content provider uri>
OFC the table must be accessable (we should have Read or write permissions), but we have another accessable table we can make use of it to reach the protected table.
Example: passwords table is accessable but key isn’t and we have this command content query --uri content://.....DBContentProvider/passwords we can make use of projection for sqli like this content query --uri content://.....DBContentProvider/passwords --projection "* from key--" so the query became select * from key -- from passwords ... but all after the – is commented so we can ignore it now and celebrate with the key data we got.
If the protected uri isn’t defined in regex we can query it directly like this content query --uri content://.....DBContentProvider/keys/
Insertion in DB: we can see its syntax from the help of adb shell content.
Deep links
Deep Links can be implicit or explicit
They are links to specific part of an application, so with links you can access apps not only browsers.
And this is the reason for opening youtube app when we click on a youtube video link instead of opening the browser.
The app which is able to handle deep links has intent filter with category : browsable.
The intent filter may also contain one or more data tags.
this is example:
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data android:scheme="hex"/>
<data android:host="open"/>
<data android:host="flag"/>
</intent-filter>
we can access this component using the url hex://open or hex://flag
Example
acode is IDE for programming using the phone and when you decompile its apk you will find that it has an intent filter with a category browsable and the data scheme is acode and after digging in the source you can see that if we want to install a plugin we the url should be acode://plugin/install/<plugin ID>.
If you can register a malicious plugin then this functionality will be critical as you can force the victim to install it if he clicked the link.
The speech above is implicit deeplink.
Chrome on Android implements a custom scheme intent: with a lot more features than the regular deep links.
It has many features
- It’s a generic intent
- Control the action and category
- Target specific app and class
- Add extra values
This is called explicit deeplink at which only specified app can handle the deep link which lowers the risk.
There another way to decrease the risk which is app links
apps with httpor https schemes maybe used to hijack websites, but this can avoided with app links.
by making this intent filter <intent-filter android:autoVerify="true"> we will avoid the vulnerability
but this link must be registered through Google Search Console.
If the website is requested, assetlinks.json file must be included under /.well-known/ directory, and the app itself should be declared as an authorized app.
Web View
It’s a component that allows developers to embed web content into the app (acts as browser within the app).
It consists of
- Browser Engine: render HTML, CSS , JS to create the UI
- JS Engine: resposible for js execution and DOM manipulation
- Android Networking Framework: establish connections and handle https requests and fetching HTML, CSS, JS pages from a server
- performance enhancement: done by using GPU to enhance visual quality and responsiveness
signing
It’s needed in many things like keeping track if there’s an update for the app in the store
package name isn’t enough because it’s unique on the phone only but we can create apps with the same package name of other apps in the store.
So the developer signs the application with a private key and the signature with the package name are used to know that the app on our phone is the one on the store and this update is for it.
Private keys used for signing applications must be super safe.
This process is for verifing the author of the app.
we can sign 2 different apps with the same signature so they can share data together without the need of exported components so the components are no longer exposed to the whole world, but the app we need to exchange the data with only.
If we want to modify app.
use apktool to decompile the apk using apktool d game.apk
you will get the decompiled files and you can modify what you want
build the apk again apktool b game.apk
We can’t install the apk if it isn’t signed so we sign it using zipalign for preparing offset for the certificate to be placed in the correct place and apksigner for signing the app
before android 11 we could use jarsigner directly for signing
Let’s see the process in more details
generation the key
keytool -genkey -v -keystore <path/to/keystore file> -alias alias_name -keyalg RSA -keysize 2048 -validity 365
-getkey for generating the private key
-v make the certificate human readable
keystore is a file which is the place at which the key will be stored
alias it’s the way we will define the key
note that many keys can be saved in the same keystore but of course the alias will be different
for signing
zipalign -v 4 base.apk out.apk
apksigner sign --ks-key-alias <alias name> -ks <path/to/keystore file> out.apk
alias is needed if there are more than a key in the keystore
METAINF dir contains all signing information so it must exist after signing
Common Application Strings
We may find useful strings to get more info
Hardcoded Strings
can be found in: resources/strings.xml, activity source code
we may find: login creds, api key, exposed url, firebase URLs
-
Android Dynamic Analysis
Dynamic Analysis
It’s about testing and evaluating a program while software is running.
SSL pinning
Security methodology to ensure that app’s traffic isn’t being intercepted (prevent from Man In The Middle)
Traffic is verified using certificate
Even if we can import certificate into phone the apps may not trust this certificate
Proxies
Burpsuite (common)
Proxyman (used on MACOS only)
even when you configure the proxy and add the certificate, some apps may not work.
because apps won’t be able to authenticate the server (which is burp in this case)
There are many ways to bypass SSL like Frida, objection.
Frida
In the smart for there’s JVM (Java Virtual Machine) and all the app code is stored there.
any class code is loaded from JVM when it’s used.
Frida is hooking into this JVM and manipulates the run time data, so the code can be changed dynamically from there.
Frida consists of FRIDA SERVER on the smart phone and FRIDA CLIENT on our laptop.
We can communicate with these instances using JavaScript or python.
The Frida server hooks into the JVM using JS and the server now can modify the code in the memory, we get access to those classes, methods, etc…
Installation of FRIDA
Frida client on our laptop
pip3 install frida-tools
Frida server on the mobile or emulator
install the server from here
decompress frida server file and move it to the emulator using adp push <path to frida server> /data/local/tmp
/data/local/tmp is the target path and we choosed it because it’s where we can ran executables
chmod +x frida server in the emulator (adb shell)
run frida binary and now the server is running (need root privileges)
you have frida server running we can test the connection from the client using frida-ps which will list the processes running on the smart phone and send the output to the client.
hooking
It’s the process of overriding method as example and this is why frida so powerful
first we will start with a basic example of hooking an activity and overriding onResume() method to print anything.
onResume() is method called when we move the app to background and return it to foreground again
we will use this script
Java.perform(function() {
const Activity = Java.use('android.app.Activity');
Activity.onResume.implementation = function () {
send('onResume() got called! Let\'s call the original implementation');
this.onResume();
};
});
and we will break it down later, but uptil now It manipulates onResume() method by making it send a specific message
So this message will be sent when we go to background and start the app again in the foreground.
Calling a method
in case of static methods
Get a reference to the class
call the static method like this class-reference.method
in case of Class methods
Get a reference to the class
create a reference to the object from this class using var playerInstance = playerClassReference.$new()
call the method like this object-reference.method
Note that this process creates object each time !! we want to control specific object (we will know that later)
working with existing objects
Now we want to manipulate existing object rather than creating a new one.
This operation is done by scanning the memory for object of the class we want and once we catch the object we can manipulate it.
Frida can do this task in easy way using this Java.choose(className, callbacks)
classname: the whole name including the package
callbacks: consists of functions like:
onMatch(instance): contains code if we found an instance
onComplete(): contains code if the scan is finished
Java.perform(function() {
// We are scanning the application memory for existing instances of the Player - Class.
Java.choose('com.apphacking.fridafunc.Player', {
// onMatch - Callback => If an instance has been found,
onMatch: function(instance) {
// code if an instance has been found
send("An instance of the player class has been found = " + instance)
instance.lives.value = 9005; // to update a variable we use .value
instance.increaseLive();
send("The instance lives = " + instance.lives.value);
},
// onComplete - Callback => Finished scanning the app memory regarding to the instance.
onComplete: function() {
send("Frida has finished scanning the application memory for player instances")
}
})
})
Instance as parameter
consider we have a boss class which has object of item class as a parameter passed to the constructor of the boss.
If we want to create an instance of the boss we need an instance of the item first, so our steps will be:
Getting the classs reference of the item
Creating a new Item Instance
Getting the class reference of the boss
Creating a new boss instance
and this as the example of the script
Java.perform(function() {
// Getting the class reference of the item class.
var itemClassReference = Java.use('com.apphacking.fridainstance.Item');
// Creating a new item instance
var itemInstance = itemClassReference.$new(100000);
// Getting the class reference of the boss class.
var bossClassReference = Java.use('com.apphacking.fridainstance.Boss');
// Creating a new boss instance with the newly created item-instance as parameter.
var bossInstance = bossClassReference.$new(itemInstance);
bossInstance.hitpoints = 900000;
})
We created a new instance of the item class and we used it, but what if we want to use an existing instance ??
very simple, instead of creating a new object of item we can search in the memory for an existing one and once we find the instance we use it to create the instance of boss object.
Java.perform(function(){
// Scanning the app memory for an exisiting item instance
Java.choose('com.apphacking.fridainstance.Item', {
// If the item instance has been found
onMatch: function(itemInstance) {
// Getting the boss class reference
var bossClassReference = Java.use('com.apphacking.fridainstance.Boss');
// Creating a new bossInstance with the item instance (found) as parameter
var bossInstance = bossClassReference.$new(itemInstance);
},
onComplete: function() {
// Done scanning the app memory
send("Scanning done");
}
});
})
hooking a constructor
The constructor is the function which is called when the object is created and hooking it is a little bit different
in case of having one constructor
classReference.$init.implementation = function(){
}
in case of having more than one constructor we will user overloading
classReference.$init.overload('int').implementation = function(){
}
UI threads
in some situations you will need to create instance of object whose constructor interacts with the ui.
in this case if we just created the instance we will get error.
The solution is schedule this operation on the main thread (UI thread) and this is done like this
Java.scheduleOnMainThread(function(){
var alienInstance = classRef.$new(param);
})
now the creation of the instance is done on the UI thread and the error is prevented.
Hooking the Native Development Kit (NDK)
We hooked java functions running in JVM, but what if we have native code writted in CPP as example.
To hook a native fucnion we use interceptor.attach(target,callbacks)
target: pointer of the function we want to hook
callbacks: can be
onEnter: easy access to params
onLeave: easy access to return values
CPP code is included within Java code like this
static {
System.loadlibrary("native.lib");
}
native.lib which is CPP code is now loaded within the current activity context
We need to build a bridge from Java world to CPP to call the functions within the CPP code
this can be done like this
public native String encryptString(String pass,int round);
This is the prototype of this function in java world now.
and now we can call this function like this
<snip>
...
encryptString(pwd,round);
...
<snip>
when we look at the cpp code we will see it’s different in argumens as example
Java_com_apphacking_ndkfrida_MainActivity_decryptString(
JNIEnv* env,jobject,jstring password,int rotation
){
...
return env->NewStringUTF(encryptedvar.c_str());
}
We have these parameters:
- JNIEnv* env: pointers to all the NDKfunctions
- jobject: pointer to the current object
- jstring password: is corresponding to String pass in the java and we are concerned with the data type not the name
- int rotation: is corresponding to int round
and this in return value we make use of the env pointer and NewStringUTF() to make a compatible string in java world.
Note: if we have the prototype of the function in java world as we saw above, we can hook and modify it rather than hooking the native function itself.
In other cases we will be forced to interact with the native functions, so let’s see what can we do
To attach to the function we need a pointer to this function, with frida we can do this:
listing the NDK methods
now you have the pointer of each function
you also have access to parameters and return value through onEnter and onLeave functions
-
Android Basics
Android Architecture
Android is based on linux OS, so the android phone can take commands like any linux device ls, cd, rm, etc..
Folders and Apps depend on the linux os permission model
The figure below shows the main components of Android platform
System Apps
This layer includes both the pre-installed applications like Camera & Calender and the 3rd pary apps which is installed by the user like facebook.
The apps run within the Android runtime
Java API Framework
Allows the app to interact with other apps and it also provides abstraction for HW access
It also manages the UI
consists of many things like:
Content Provider: helps in sharing data to other apps via specific directory which should be exported content://<app-URI>/directory
View System: Making the UI of the application
Managers:
Activity => the single activity is a single UI screen of the app
Notification => application’s reminders and popups
etc….
Android Runtime
The base of the app and it powers the app with the help of core libraries
Virtual Machine to generate .dex file as a result of compliation and optmization
Native C/C++ libraries
In the same layer of Android runtime
Contains core libraries like sqlite for db, openssl for secure connection, etc…
Hardward Abstraction Layer (HAL)
Allows apps to access HW components irrespective of the type or manufacturer of the device like camera, bluetooth, GPS, etc…
New HAL types like IOT devices, gaming peripherals, etc..
Linux Kernel
Supp multiple CPU types (ARM, SoC, 32 bit, 64 bit)
The version of the Android Runtime/ API version is determined in Manifest => min SDK version
The higher the better but there’s a trade of between using higher version and serving as many customers as possible because not all phones supports the higher versions
Low version means more danger (more vulnerable)
The kernel also controls the available drivers by which the access to the devices during runtime occurs
Application Journey
Source Code (written in Java or Kotlin) + lib + resources ==compile==> DEX
The source code is compiled but lib just helps in compilation which is done by virtual machine giving DEX file
DEX ==build==> APK
APK ==sign==> signed APK
The APK must be signed using a certificate exist at the developer
The signed APK is uploaded to google play and now can be installed on user’s device
Android Security Model
Android consists of 2 security layers: DAC-Discretionary Access Control & MAC-Mandatory Access Control
Each application has its on user who is the oner of the app.
users have UID between 10000 and 999999
the username u0_a188 has UID 10188
Apps can’t interact ith each other unless explicitly granted permissions or Content Provider/Broadcast Receiver is exposed.
Application components
Activity
It’s the UI with which the user interacts
Each activity in the app is a single screen
login page is an activity and register page is another activity
Services
It handles the background processes the works behind the UI like downloading or any process
Broadcast Reciever
It handles communication between the apps with the OS of Android.
When you connect ur phone to internet the system broadcasts a message saying that the phone is connected to the internet then the apps do their work depending on getting connected to internet
Local Storage
How the app is stored in the system
consists of
Shared Preferences: Sometimes to improve the application’s performance some data is stored on the device locally
DB (content provider): data is saved in SQlite db, The app reached the data through the content provider which must be configured properly to avoid local sqli vulnerability
Files: stored for each app and isolated from other app and sometimes stored on SDcard this was vulnerable in android 4.4 and the SDcard could be accessed by other apps
Additional components
Fragments: part of activity
Views
Layouts
Intents: method by which the components communicate (discussed later)
Resources
Manifest: The most important file in the app as it contains all the components of the application (discussed later)
Developer Options
It offers you a collection of great tools that we will use in the upcoming sections like
USB-Debugging
Select mock location app
Select debug app/ Wait for debugger
Pointer Location
Bluetooth HCI Snoop Log
Enabling Developer Options
Go to System
About Phone
Go to build number and click it, then you will see if you are developer and if not it will tell you how many clicks you should do to be developer
ADB (Android Debug Bridge)
Let’s look on Its components and how it works.
ADB Components
The components are:
adb server on your machine
adbd (the daemon on the mobile) running by default on the device, so you don’t need to install it or somehink like that
adb client (binary) (in platform-tools and it comes with sdk)
adb protocol is text based protocol and we will look into it in the future
ADB process
How it works:
adb client sends command to adb server
adb server sends the command to the mobile
The command is executed on the mobile then sends it back the server
The response is forwarded back to the client
if we have single device connected we can use adb shell command, but if there are multiple devices we will use abd -s <serial> shell
ABD-Fowarding
consider there’s a service on port 31415 on the mobile, but it’s accessed locally only.
to access it through our localhost we use port forwarding
by using adb forward tcp:1337 tcp:31415 we will be able to access port 31415 on the mobile by accessing localhost:1337
Forwarding can also be reverse, but it’s not popular
by using adb reverse tcp:80 tcp:8080 we will be able to access port 8080 on our localhost through the mobile on port 80
Additional Notes
sdcard and tmp directory are both accessible from our local device to the mobile without root privileges so we can use adb push file path_on_mobile and the path can be /sdcard/
adb push to uplaod file to the mobile
adb pull to download file from the mobile
logcat is a great command you can run when u run app and the logs will be stored and you can get interesting info
adb kill server then start again this will resolve many issues if occured with the server
Android Application Structure
assets : contains resources used in the app like images, music, etc…
com : no interesting data for us
lib : contains .so files which are compiled c/cpp files because they are better than java in specific task like rendering 3d effects. (sometimes developer hide data in c/cpp code instead of java code)
armeabi : compiled for the platform of the original device
x86 : compiled for our vm as example
META-INF : related to signing the application
res : maybe considered like assets directory as it contains images, etc..
AndroidManifest.xml: We will dive into it later as it very important
classes.dex : The most important file for us as it contains the JAVA source code.
and java is compiled in dex format
resources.arsc : contains resources like resources used in the application.
Let’s recap this
DEX/ODEX files
We are going to discuss it a very high view
You have an app and it is got compiled using Java Virtual Machine
For Java app on your PC : It’s got compiled to Java Bytecode (main.class) and it is not good for smart phone as it need more resources which won’t fit with mobile battery
For mobile app : IT’s got compiled to dalvik executable (classes.dex) which is suitable for smart phones
Note: classes.dex contains at most 65535 methods and if we have more than this number we will have many .dex files which is called MultiDexing
Decompilation
To decompile an apk we need to get it first
And to get an apk
$ adb shell
$ pm list packages
$ pm path
$ adb pull <path>
to compile the app we use
apktool d <APK>
to build the app again
apktool b <APP PATH>
There are options like:
-r to not decode resources like android manifest as it will cuz problems if decoded in this case
-s to not decode source code as it will cuz problems if decoded in this case
--force-manifest this is good if the problems in resources other than manifest so it will decode manifest even if decoding resources is set to false
When we compile we will get these files (let’s compare them to unzipping we saw before)
The identical files:
assets
lib
META-INF and AndroidManifest.xml = original
res and resources.arsc = res and note that it contains values dir which contains resources.arsc data
com = in unknown
Different
smali which contains .dex files so we have java src code and we have .smali files
Touch background to close